#include "swiic.h"
#include "bsp_delay.h"
/*
*函数名：i2c_Start
*形参：IIC_InitTypeDef IIC
返回值：无
*/
void IIC_Start(IIC_InitTypeDef* IIC)
{
	SDA_OUT();
	__SDA_1;        		//SDA线高电平，这里就是配置了对应的GPIO管脚输出高电平而已
	__SCL_1;
	IIC_Delay();        //需要保证你的SDA线高电平一段时间，如下面SDA=0，这不延时的话，直接变成0
	__SDA_0;
	IIC_Delay();
	__SCL_0;
	IIC_Delay();
}

/*
*函数名：IIC_Stop
*形参：IIC_InitTypeDef IIC
返回值：无
*/
void IIC_Stop(IIC_InitTypeDef* IIC)
{
	SDA_OUT();
	__SCL_0;
	__SDA_0;        //SDA线低电平，这里就是配置了对应的GPIO管脚输出高电平而已
	IIC_Delay();
	__SCL_1;
	IIC_Delay();         //需要保证你的SDA线高电平一段时间，如下面SDA=0，这不延时的话，直接变成0
	__SDA_1;
	IIC_Delay();
}

/*
*函数名：IIC_WaitAck
*函数功能：CPU产生一个时钟，并读取器件的ACK信号
*形参：IIC_InitTypeDef* IIC
*返回值：返回0表示正确应答，1表示无应答
*/
uint8_t IIC_WaitAck(IIC_InitTypeDef* IIC)
{
	uint8_t timeout = 0;
	__SDA_1;        //CPU释放总线
	SDA_IN();				//SDA设置为输入
	IIC_Delay();        
	__SCL_1;        //cpu驱动SCL=1，此时器件会返回ACK信号
	IIC_Delay();
	while(__SDA_READ)
	{
		timeout++;
		if(timeout > OUTTIME)
		{
			__SCL_0;
			IIC_Delay();
			SDA_OUT();
			return 1;
		}
	}
	__SCL_0;
	IIC_Delay();
	SDA_OUT();
	return 0;
}


/*
*函数名：IIC_Ack
*形参：IIC_InitTypeDef* IIC
*返回值：无
*/
void IIC_Ack(IIC_InitTypeDef* IIC)
{
	__SDA_0;    //cpu驱动SDA=0
	IIC_Delay();
	__SCL_1;    //产生一个高电平时钟
	IIC_Delay();
	__SCL_0;
	IIC_Delay();
	__SDA_1;    //cpu释放总线
	IIC_Delay();
}


/*
*函数名：IIC_NAck
*形参：IIC_InitTypeDef* IIC
*返回值：无
*/
void IIC_NAck(IIC_InitTypeDef* IIC)
{
	__SDA_1;    //cpu驱动SDA=1
	IIC_Delay();
	__SCL_1;    //产生一个高电平时钟
	IIC_Delay();
	__SCL_0;
	IIC_Delay();
}

/**
 @brief CPU向I2C总线设备发送8bit数据
 @param IIC 句柄,ucByte -[in] 等待发送的字节
 @return 无
*/
void IIC_SendByte(IIC_InitTypeDef* IIC,uint8_t _ucByte)
{
	uint8_t i;

	/* 先发送字节的高位bit7 */
	for (i = 0; i < 8; i++)
	{		
		if (_ucByte & 0x80)
		{
			__SDA_1;
		}
		else
		{
			__SDA_0;
		}
		IIC_Delay();
		__SCL_1;
		IIC_Delay();	
		__SCL_0;

		_ucByte <<= 1;	/* 左移一个bit */
	}
}

/**
 @brief CPU从I2C总线设备读取8bit数据
 @param IIC IIC_InitTypeDef句柄
 @return 读到的数据
*/
uint8_t IIC_ReadByte(IIC_InitTypeDef* IIC,uint8_t *read)
{
	uint8_t i;
	uint8_t value;
  SDA_IN();
	/* 读到第1个bit为数据的bit7 */
	value = 0;
	for (i = 0; i < 8; i++)
	{
		value <<= 1;
		__SCL_1;
		IIC_Delay();
		if (__SDA_READ)
		{
			value++;

		}
		__SCL_0;
		IIC_Delay();
	}
	SDA_OUT();
	*read = value;
	return value;
}

uint8_t IIC_Write(IIC_InitTypeDef* IIC,uint8_t *pData)
{
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr);
	IIC->status |= IIC_WaitAck(IIC);
	
	IIC_SendByte(IIC, *pData);
	IIC->status |= IIC_WaitAck(IIC);
	
	IIC_Stop(IIC);
	if(IIC->status) 
			return (1);
	else
			return (0);
}

uint8_t IIC_Read(IIC_InitTypeDef* IIC,uint8_t *pData)
{
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr | 0x01);
	IIC->status |= IIC_WaitAck(IIC);
	
	IIC_ReadByte(IIC, pData);
	IIC_NAck(IIC);
	
	IIC_Stop(IIC);
	if(IIC->status) 
			return (1);
	else
			return (0);
}


uint8_t IIC_Mem_Write(IIC_InitTypeDef* IIC,uint16_t MemAddr,uint8_t MemAddSize,uint8_t *pData,uint16_t Size){
	uint16_t i;
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr);
	IIC->status = IIC_WaitAck(IIC);
	
	if(MemAddSize == IIC_MEMADD_SIZE_16BIT)
	{
		IIC_SendByte(IIC, (uint8_t)(MemAddr>>8));
		IIC->status |= IIC_WaitAck(IIC);
	}
	IIC_SendByte(IIC, (uint8_t)(MemAddr&0xFF));
	IIC->status |= IIC_WaitAck(IIC);
	
	for(i=0; i<Size;i++){
		IIC_SendByte(IIC, *(pData+i));
		IIC->status |= IIC_WaitAck(IIC);
	}
	
	IIC_Stop(IIC);
	if(IIC->status) 
			return (1);
	else
			return (0);
}

uint8_t IIC_Read_Data(IIC_InitTypeDef* IIC,uint8_t *pData,uint16_t Len)
{
	uint16_t i;
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr | 0x01);
	IIC->status |= IIC_WaitAck(IIC);
	
	for(i=0; i < Len;i++){
		IIC_ReadByte(IIC, pData+i);
		if(i == Len -1){
			IIC_NAck(IIC);
		}else{
			IIC_Ack(IIC);
		}
	}
	
	IIC_Stop(IIC);
	if(IIC->status) 
			return (1);
	else
			return (0);
}

uint8_t IIC_Mem_Read(IIC_InitTypeDef* IIC,uint16_t MemAddr,uint8_t MemAddSize,uint8_t *pData,uint16_t Size){
	uint16_t i;
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr);
	IIC->status = IIC_WaitAck(IIC);
	
	if(MemAddSize == IIC_MEMADD_SIZE_16BIT)
	{
		IIC_SendByte(IIC, (uint8_t)(MemAddr>>8));
		IIC->status |= IIC_WaitAck(IIC);
	}
	IIC_SendByte(IIC, (uint8_t)(MemAddr&0xFF));
	IIC->status |= IIC_WaitAck(IIC);
	
	IIC_Start(IIC);
	IIC_SendByte(IIC, IIC->addr | 0X01);
	IIC->status = IIC_WaitAck(IIC);
	
	for(i=0; i<Size;i++){
		IIC_ReadByte(IIC, pData+i);
		if(i == Size -1){
			IIC_NAck(IIC);
		}else{
			IIC_Ack(IIC);
		}
	}
	IIC_Stop(IIC);
	
	if(IIC->status) 
			return (1);
	else
			return (0);
}
#ifdef USE_HAL_DRIVER

void HAL_Delay_us(uint32_t nus)
{
//  //将systic设置为1us中断
//  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000000);
//  //延时nus
//  HAL_Delay(nus-1);
//  //恢复systic中断为1ms
//  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  
  uint32_t old_val,new_val,val;
 
    if(nus > 900)
    {
        for(old_val = 0; old_val < nus/900; old_val++)
        {
            HAL_Delay_us(900);
        }
        nus = nus%900;
    }
 
    old_val = SysTick->VAL;
    new_val = old_val - 64*nus;
    if(new_val > 0)
    {
        do
        {
            val = SysTick->VAL;
        }
        while((val < old_val)&&(val >= new_val));
    }
    else
    {
        new_val +=64*1000;
        do
        {
            val = SysTick->VAL;
        }
        while((val <= old_val)||(val > new_val));
 
    }
}


void IIC_GPIO_INPUT(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin){
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  GPIO_InitStruct.Pin = GPIO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}

void IIC_GPIO_OUTPUT(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin){
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  GPIO_InitStruct.Pin = GPIO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}

#endif

void IIC_Init(IIC_InitTypeDef* IIC)
{
	IIC_Stop(IIC);
}
//以下为初始化示例，支持复用
#if 1
IIC_GPIO ONE_SCL = {IIC_SCL_Port,IIC_SCL_Pin};
IIC_GPIO ONE_SDA = {IIC_SDA_Port,IIC_SDA_Pin};

IIC_InitTypeDef ONE_IIC;

void IIC_ONE_Init(uint8_t Sladdr){
	ONE_IIC.SCL = ONE_SCL;
	ONE_IIC.SDA = ONE_SDA;
  ONE_IIC.addr = Sladdr;

	IIC_Init(&ONE_IIC);
}
#endif
